package org.tigris.atlas.uddi.weblogic;

import java.io.IOException;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import weblogic.uddi.client.structures.datatypes.AccessPoint;
import weblogic.uddi.client.structures.datatypes.BindingTemplate;
import weblogic.uddi.client.structures.datatypes.BindingTemplates;
import weblogic.uddi.client.structures.datatypes.BusinessInfo;
import weblogic.uddi.client.structures.datatypes.BusinessInfos;
import weblogic.uddi.client.structures.datatypes.BusinessKey;
import weblogic.uddi.client.structures.datatypes.BusinessService;
import weblogic.uddi.client.structures.datatypes.ErrInfo;
import weblogic.uddi.client.structures.datatypes.FindQualifiers;
import weblogic.uddi.client.structures.datatypes.Name;
import weblogic.uddi.client.structures.datatypes.Result;
import weblogic.uddi.client.structures.datatypes.ServiceInfo;
import weblogic.uddi.client.structures.datatypes.ServiceInfos;
import weblogic.uddi.client.structures.datatypes.ServiceKey;
import weblogic.uddi.client.structures.exception.UDDIException;
import weblogic.uddi.client.structures.exception.XML_SoapException;
import weblogic.uddi.client.structures.request.FindBusiness;
import weblogic.uddi.client.structures.request.FindService;
import weblogic.uddi.client.structures.request.GetServiceDetail;
import weblogic.uddi.client.structures.response.BusinessList;
import weblogic.uddi.client.structures.response.DispositionReport;
import weblogic.uddi.client.structures.response.ServiceDetail;
import weblogic.uddi.client.structures.response.ServiceList;

public class Inquiry {

	private static final String EXACT_NAME_MATCH = "exactNameMatch";
	private static final String CASE_SENSITIVE_MATCH = "caseSensitiveMatch";
	private static final String SORT_BY_NAME_DESC = "sortByNameDesc";
	
	private static Log log = LogFactory.getLog( Inquiry.class );
	
	private weblogic.uddi.client.service.Inquiry inquiry = null;
	
	private Inquiry() {
		inquiry = new weblogic.uddi.client.service.Inquiry(); 
		System.setProperty("java.protocol.handler.pkgs", "weblogic.net");
		String uddiUrl;
		try {
			uddiUrl = UddiProperties.getUddiUrl();
			inquiry.setURL( uddiUrl );
		} catch (IOException e) {
			log.error( "Unable to create UDDI Inquiry", e );
			inquiry.setURL( null );
		}
	}
	
	public static String findServiceEndpoint(String businessName, String serviceName) {
		Inquiry inquiry = new Inquiry();
		
		BusinessKey businessKey = inquiry.findBusinessKeyByName( businessName );
		if( businessKey == null ) {
			return null;
		}
		
		ServiceKey serviceKey = inquiry.findServiceKeyByName( businessKey, serviceName );
		if( serviceKey == null ) {
			return null;
		}
		
		return inquiry.findServiceEndpoint( serviceKey );
	}
	
	private BusinessKey findBusinessKeyByName(String businessName) {
		BusinessKey businessKey = null;
		
		try {
		      Name name = new Name( businessName );
	
		      FindQualifiers fqs = new FindQualifiers();
	
		      fqs.addFindQualifier( EXACT_NAME_MATCH );
		      fqs.addFindQualifier( CASE_SENSITIVE_MATCH );
	
		      FindBusiness fb = new FindBusiness();
	
		      // set all the arguments and attributes of the message
		      fb.setFindQualifiers(fqs);
		      fb.setName(name);
	
		      BusinessList rBusinessList = inquiry.findBusiness(fb);
		      BusinessInfos rBusinessInfos = rBusinessList.getBusinessInfos();
	
		      if (rBusinessInfos == null) {
		    	  log.info( "Could not locate Business: " + name.getValue() );	
		    	  return null;
		      } 
	
		      Vector rBusinessInfoVector = rBusinessInfos.getBusinessInfoVector();
		      if (rBusinessInfoVector.size() != 1) {
		        	log.error( "Incorrect business list size. Expected: 1, was: " + rBusinessInfoVector.size() );
			        return null;
		      } 
	
		      BusinessInfo rBusinessInfo;
	
		      rBusinessInfo = (BusinessInfo) rBusinessInfoVector.elementAt(0);
	
		      Name rName = rBusinessInfo.getName();
	
		      businessKey = new BusinessKey( rBusinessInfo.getBusinessKey() );
	    } 
		catch (UDDIException ue) {
			log.error( "UDDIEXception " + ue.getFaultActor() + " " + ue.getFaultCode() );

			DispositionReport dr = ue.getDispositionReport();
			Vector res = dr.getResultVector();
			Result r = (Result) res.elementAt(0);
			ErrInfo ei = r.getErrInfo();

			log.error( "ErrInfo : " + ei.getValue() );
	    } 
		catch (XML_SoapException exp) {
			log.error( "XML_SoapException " + exp.getMessage(), exp );
	    } 
		catch (Exception e) {
			log.error( "Exception", e );
	    } 
		
		return businessKey;
	}
	
	private ServiceKey findServiceKeyByName(BusinessKey businessKey, String serviceName) {
		ServiceKey serviceKey = null;
		
		try {
			Name name = new Name( serviceName );

			FindQualifiers fqs = new FindQualifiers();

			fqs.addFindQualifier( SORT_BY_NAME_DESC );
			fqs.addFindQualifier( CASE_SENSITIVE_MATCH );

	      	FindService fs = new FindService();

	      	// set all the arguments and attributes of the message
	      	fs.setBusinessKey(businessKey.getValue());
	      	fs.setFindQualifiers(fqs);
	      	fs.setName(name);

	      	ServiceList rServiceList = inquiry.findService( fs );

	      	ServiceInfos rServiceInfos = rServiceList.getServiceInfos();

	      	if (rServiceInfos == null) {
	      		log.info( "No service found in UDDI named: " + serviceName );
	      		return null;
	        } 

	      	Vector rServiceInfoVector = rServiceInfos.getServiceInfoVector();
	      	
	      	if( rServiceInfoVector.size() > 1 ) {
	        	log.error( "Incorrect service list size. Expected: 1, was: " + rServiceInfoVector.size() );
		        return null;
	      	}
	      	
	      	ServiceInfo rServiceInfo = (ServiceInfo) rServiceInfoVector.elementAt( 0 );
	      	serviceKey = new ServiceKey( rServiceInfo.getServiceKey() );

	    }
		catch (UDDIException ue) {
			log.error( "UDDIEXception " + ue.getFaultActor() + " " + ue.getFaultCode() );

			DispositionReport dr = ue.getDispositionReport();
			Vector res = dr.getResultVector();
			Result r = (Result) res.elementAt(0);
			ErrInfo ei = r.getErrInfo();

			log.error( "ErrInfo : " + ei.getValue() );
	    } 
		catch (XML_SoapException exp) {
			log.error( "XML_SoapException " + exp.getMessage(), exp );
	    } 
		catch (Exception e) {
			log.error( "Exception", e );
	    } 
		
		return serviceKey;

	}
	
	private String findServiceEndpoint(ServiceKey serviceKey) {
		String serviceUri = null;
		
		try {
			Vector serviceKeyVector = new Vector();
			serviceKeyVector.add(serviceKey);

		    GetServiceDetail gsd = new GetServiceDetail();
		    
		    // set all the arguments and attributes of the message
		    // follow the uddi.org specification for details.
		    gsd.setServiceKeyVector( serviceKeyVector );

		    ServiceDetail rServiceDetail = inquiry.getServiceDetail( gsd );

		    Vector rBusinessServiceVector = rServiceDetail.getBusinessServiceVector();

	      	if( rBusinessServiceVector.size() > 1 ) {
	        	log.error( "Incorrect business service list size. Expected: 1, was: " + rBusinessServiceVector.size() );
		        return null;
	      	}
	      	
		    BusinessService rBS = (BusinessService) rBusinessServiceVector.elementAt( 0 );

		    Vector rDesVector = rBS.getDescriptionVector();
		    BindingTemplates rBTs = rBS.getBindingTemplates();
		    Vector rBTVector = rBTs.getBindingTemplateVector();

	      	if( rBTVector.size() > 1 ) {
	        	log.error( "Incorrect binding template list size. Expected: 1, was: " + rBusinessServiceVector.size() );
		        return null;
	      	}
	      	
		    BindingTemplate returnBindingTemplate = (BindingTemplate) rBTVector.elementAt( 0 );
		    
		    AccessPoint rAP = returnBindingTemplate.getAccessPoint();
		    if (rAP != null) {
		    	serviceUri = rAP.getValue();
		    }
		    else {
		    	log.error( "No URI found for service key: " + serviceKey.getValue() );
		    }
		}
		catch (XML_SoapException exp) {
			log.error( "XML_SoapException " + exp.getMessage(), exp );
	    } 
		catch (Exception e) {
			log.error( "Exception", e );
	    } 
		
		return serviceUri;
	}

}
